/**
 *     Aedict - an EDICT browser for Android
 Copyright (C) 2009 Martin Vysny

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.jm.jisho;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.jm.jisho.dict.DictEntry;
import com.jm.jisho.dict.DictTypeEnum;
import com.jm.jisho.dict.Dictionary;
import com.jm.jisho.dict.Edict;
import com.jm.jisho.dict.EdictEntry;
import com.jm.jisho.dict.LuceneSearch;
import com.jm.jisho.dict.MatcherEnum;
import com.jm.jisho.dict.SearchQuery;
import com.jm.jisho.dict.TanakaSearchTask;
import com.jm.jisho.kanji.Deinflections;
import com.jm.jisho.kanji.Deinflections.Deinflection;
import com.jm.jisho.kanji.RomanizationEnum;
import com.jm.jisho.kanji.VerbDeinflection;
import com.jm.jisho.dict.util.Check;
import com.jm.jisho.dict.util.DictEntryListActions;
import com.jm.jisho.dict.util.ShowRomaji;
import com.jm.jisho.dict.util.android.DialogUtils;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.TwoLineListItem;

/**
 * Provides means to search the edict dictionary file.
 * 
 * @author Martin Vysny
 */
public class DictionaryActivity extends ListActivity {
	private ShowRomaji showRomaji;
	private static final int ID_ADD = 1;
	private static final int ID_ACCEPT = 2;
	private static final int ID_UPLOAD = 3;	

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		showRomaji.loadState(savedInstanceState);
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		showRomaji.saveState(outState);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.action, menu);
	    return true;
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.dictionary_layout);

		
		

		final SearchQuery query = new SearchQuery(DictTypeEnum.Edict);
		query.isJapanese = false;
		query.matcher = MatcherEnum.StartsWith;
		query.query = new String[] { "a" };
		query.langCode = JJishoApp.getConfig().getSamplesDictLang();
		List<DictEntry> dictList = new ArrayList<DictEntry>();
		try {
			dictList =  LuceneSearch.singleSearch(query, null, true);
		} catch (Exception e) {

		}
	
		String[] lists = new String[200];
		
		for (int i=0; i<dictList.size(); i++){
			System.out.println("Search ... " + dictList.get(i));
			lists[i] = dictList.get(i).english;
		}
			
		
		// Get a reference to the AutoCompleteTextView in the layout
		AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete_country);
		// Get the string array
		//String[] countries = getResources().getStringArray(R.array.countries_array);
		// Create the adapter and set it to the AutoCompleteTextView 
		ArrayAdapter<String> adapter = 
		        new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, lists);
		textView.setAdapter(adapter);

		showRomaji = new ShowRomaji() {

			@Override
			protected void show(boolean romaji) {
				((ArrayAdapter<?>) getListAdapter()).notifyDataSetChanged();
			}
		};

		ActionItem addItem 		= new ActionItem(ID_ADD, "Add", getResources().getDrawable(R.drawable.jp_en));
		ActionItem acceptItem 	= new ActionItem(ID_ACCEPT, "Accept", getResources().getDrawable(R.drawable.en_jp));


		final QuickAction mQuickAction 	= new QuickAction(this);

		mQuickAction.addActionItem(addItem);
		mQuickAction.addActionItem(acceptItem);

		//setup the action item click listener
		mQuickAction.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {
			@Override
			public void onItemClick(QuickAction quickAction, int pos, int actionId) {
				ActionItem actionItem = quickAction.getActionItem(pos);

				if (actionId == ID_ADD) {
					((Button)findViewById(R.id.settingbtn)).setBackgroundDrawable(getResources().getDrawable(R.drawable.jp_en));
					Toast.makeText(getApplicationContext(), "English To Japanese Selected", Toast.LENGTH_SHORT).show();
				} else {
					((Button)findViewById(R.id.settingbtn)).setBackgroundDrawable(getResources().getDrawable(R.drawable.en_jp));					
					Toast.makeText(getApplicationContext(), "Japanese to English Selected", Toast.LENGTH_SHORT).show();
				}
			}
		});

		mQuickAction.setOnDismissListener(new QuickAction.OnDismissListener() {
			@Override
			public void onDismiss() {

			}
		});

		Button btn1 = (Button) this.findViewById(R.id.settingbtn);
		btn1.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mQuickAction.show(v);
			}
		});


		/**

		findViewById(R.id.advanced).setOnClickListener(new View.OnClickListener() {

			public void onClick(View v) {
				final View g = findViewById(R.id.advancedPanel);
				g.setVisibility(g.getVisibility() == View.GONE ? View.VISIBLE : View.GONE);
			}
		});
		 */





		// check for dictionary file and download it if it is missing.
		JJishoApp.getDownloader().checkDictionary(this, new Dictionary(DictTypeEnum.Edict, null), null, false);
		JJishoApp.getDownloader().checkRequiredVersions(this);
		if (!JJishoApp.isInstrumentation) {
			new DialogUtils(this).showInfoOnce(JJishoApp.getVersion(), JJishoApp.format(R.string.whatsNew, JJishoApp.getVersion()), getString(R.string.whatsNewText));
		}
		((TextView) findViewById(R.id.aedict)).setText("JJisho " + JJishoApp.getVersion());
		new DictEntryListActions(this, true, true, true, false){

			@Override
			protected void onDelete(int itemIndex) {
				final List<DictEntry> rv = JJishoApp.getConfig().getRecentlyViewed();
				rv.remove(itemIndex);
				JJishoApp.getConfig().setRecentlyViewed(rv);
				invalidateModel();
			}

			@Override
			protected void onDeleteAll() {
				JJishoApp.getConfig().setRecentlyViewed(new ArrayList<DictEntry>());
				invalidateModel();
			}

		}.register(getListView());
		final String prefillTerm = getIntent().getStringExtra(INTENTKEY_PREFILL_SEARCH_FIELD);
		if (prefillTerm != null) {
			((TextView) findViewById(R.id.searchEdit)).setText(prefillTerm);
		}
		// setup search controls
		setupSearchControls();


	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	protected void onResume() {
		super.onResume();
		invalidateModel();
		showRomaji.onResume();
		findViewById(R.id.searchEdit).requestFocus();
		final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
	}

	private List<DictEntry> modelCache = null;

	private List<DictEntry> getModel() {
		if (modelCache == null) {
			modelCache = JJishoApp.getConfig().getRecentlyViewed();
		}
		return modelCache;
	}

	private void invalidateModel() {
		modelCache = null;
		setModel();
		findViewById(R.id.intro).setVisibility(getModel().isEmpty() ? View.VISIBLE : View.GONE);
		findViewById(R.id.recentlyViewed).setVisibility(getModel().isEmpty() ? View.GONE : View.VISIBLE);
	}

	/**
	 * Adds given entry to the "recently viewed" list.
	 * @param entry the entry, not null.
	 */
	public static void recentlyViewed(final DictEntry entry) {
		Check.checkNotNull("entry", entry);
		final List<DictEntry> entries = JJishoApp.getConfig().getRecentlyViewed();
		while (entries.size() > 15) {
			entries.remove(entries.size() - 1);
		}
		entries.remove(entry);
		entries.add(0, entry);
		JJishoApp.getConfig().setRecentlyViewed(entries);
	}

	/**
	 * Sets the ListView model.
	 */
	private void setModel() {
		final RomanizationEnum romanization = JJishoApp.getConfig().getRomanization();
		setListAdapter(new ArrayAdapter<DictEntry>(this, android.R.layout.simple_list_item_2, getModel()) {

			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				TwoLineListItem view = (TwoLineListItem) convertView;
				if (view == null) {
					view = (TwoLineListItem) getLayoutInflater().inflate(android.R.layout.simple_list_item_2, getListView(), false);
				}
				Edict.print(getModel().get(position), view, showRomaji.resolveShowRomaji() ? romanization : null);
				return view;
			}

		});
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		final DictEntry e = getModel().get(position);
		if (!e.isValid()) {
			return;
		}
		DefinitionActivity.launch(this, EdictEntry.fromEntry(e));
	}

	/**
	 * Pre-fill the string under this key in the search box.
	 */
	static final String INTENTKEY_PREFILL_SEARCH_FIELD = "prefillSearchField";

	/**
	 * Launches this activity.
	 * @param activity context.
	 * @param term if not null this string will be filled in the search box.
	 */
	public static void launch(Activity activity, String term) {
		final Intent i = new Intent(activity, DictionaryActivity.class);
		if (term != null) {
			i.putExtra(INTENTKEY_PREFILL_SEARCH_FIELD, term);
		}
		activity.startActivity(i);
	}

	private void setupSearchControls() {
		findViewById(R.id.searchEdit).setOnClickListener(new OnClickListener() {

			//TODO False - English. True - Japanese
			public void onClick(View v) {
				search(false);
			}
		});

		final CheckBox deinflect = (CheckBox) findViewById(R.id.jpDeinflectVerbs);
		deinflect.setOnCheckedChangeListener(new ComponentUpdater());
		final CheckBox tanaka = (CheckBox) findViewById(R.id.searchExamples);
		tanaka.setOnCheckedChangeListener(new ComponentUpdater());
		final CheckBox translate = (CheckBox) findViewById(R.id.translate);
		translate.setOnCheckedChangeListener(new ComponentUpdater());
		((EditText)findViewById(R.id.searchEdit)).setOnEditorActionListener(new EditText.OnEditorActionListener() {

			public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
				final String text = ((TextView) findViewById(R.id.searchEdit)).getText().toString().trim();
				if (text.length() == 0) {
					return true;
				}
				final boolean isAdvanced = findViewById(R.id.advancedPanel).getVisibility() != View.GONE;
				final RomanizationEnum r = JJishoApp.getConfig().getRomanization();
				if (!isAdvanced) {
					// search for jp/en
					final Deinflections d = VerbDeinflection.searchJpDeinflected(text, r);
					final SearchQuery en = SearchQuery.searchEnEdict(text, true);
					ResultActivity.launch(DictionaryActivity.this, Arrays.asList(en, d.query), d.deinflections);
				} else if (deinflect.isChecked() || translate.isChecked()) {
					search(true);
				} else if (tanaka.isChecked()) {
					if (!JJishoApp.getDownloader().checkDictionary(DictionaryActivity.this, new Dictionary(DictTypeEnum.Tanaka, null), null, false)) {
						return true;
					}
					final SearchQuery jp = SearchQuery.searchTanaka(JJishoApp.getConfig().getSamplesDictType(), text, true, r, JJishoApp.getConfig().getSamplesDictLang());
					final SearchQuery en = SearchQuery.searchTanaka(JJishoApp.getConfig().getSamplesDictType(), text, false, r, JJishoApp.getConfig().getSamplesDictLang());
					ResultActivity.launch(DictionaryActivity.this, Arrays.asList(en, jp), null);
				}
				return true;
			}
		});
	}

	private void search(final boolean isJapanese) {
		final boolean isAdvanced = findViewById(R.id.advancedPanel).getVisibility() != View.GONE;
		final boolean isTranslate = ((CheckBox) findViewById(R.id.translate)).isChecked();
		final String text = ((TextView) findViewById(R.id.searchEdit)).getText().toString().trim();
		if (text.length() == 0) {
			return;
		}

		final boolean isDeinflect = ((CheckBox) findViewById(R.id.jpDeinflectVerbs)).isChecked();
		final RomanizationEnum r = JJishoApp.getConfig().getRomanization();
		if (isAdvanced && isDeinflect && isJapanese) {
			final Deinflections q = VerbDeinflection.searchJpDeinflected(text, r);
			performSearch(q.query, q.deinflections);
			return;
		}
		final boolean isTanaka = ((CheckBox) findViewById(R.id.searchExamples)).isChecked();
		if (isAdvanced && isTanaka) {
			final SearchQuery q = SearchQuery.searchTanaka(JJishoApp.getConfig().getSamplesDictType(), text, isJapanese, r, JJishoApp.getConfig().getSamplesDictLang());
			performSearch(q, null);
			return;
		}
		final MatcherEnum matcher = isAdvanced ? MatcherEnum.values()[((Spinner) findViewById(R.id.matcher)).getSelectedItemPosition()] : MatcherEnum.Substring;
		final SearchQuery q = isJapanese ? SearchQuery.searchJpRomaji(text, r, matcher) : SearchQuery.searchEnEdict(text, matcher == MatcherEnum.Exact);
		performSearch(q, null);
	}

	private class ComponentUpdater implements OnCheckedChangeListener {
		public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			final Activity activity = DictionaryActivity.this;
			final Spinner matcher = (Spinner) activity.findViewById(R.id.matcher);
			final CheckBox deinflect = (CheckBox) activity.findViewById(R.id.jpDeinflectVerbs);
			final CheckBox tanaka = (CheckBox) activity.findViewById(R.id.searchExamples);
			final CheckBox translate = (CheckBox) activity.findViewById(R.id.translate);
			if (buttonView.getId() == R.id.jpDeinflectVerbs && isChecked) {
				matcher.setSelection(MatcherEnum.Exact.ordinal());
				tanaka.setChecked(false);
				translate.setChecked(false);
			} else if (buttonView.getId() == R.id.searchExamples && isChecked) {
				matcher.setSelection(MatcherEnum.Substring.ordinal());
				deinflect.setChecked(false);
				translate.setChecked(false);
			} else if (buttonView.getId() == R.id.translate && isChecked) {
				deinflect.setChecked(false);
				tanaka.setChecked(false);
			}
			matcher.setEnabled(!deinflect.isChecked() && !tanaka.isChecked() && !translate.isChecked());
			findViewById(R.id.searchEdit).setEnabled(!translate.isChecked() && !deinflect.isChecked());
		}
	}

	private void performSearch(final SearchQuery query, final List<Deinflection> deinflections) {
		if (!JJishoApp.getDownloader().checkDictionary(this, new Dictionary(query.dictType, null), null, false)) {
			// the dictionary is not yet available. An activity was popped up,
			// which offers dictionary download. Nothing to do here, just do
			// nothing.
			return;
		}
		ResultActivity.launch(this, query, deinflections);
	}
}
